#include "lightcontainer.h"

CLightContainer::~CLightContainer() 
{
    /**
     * Destructor, ensure that the memory is freed back to the heap.
     */
    for (map<string,CLight*>::iterator i = m_arrLights.begin(); 
            i != m_arrLights.end(); ++i)
    {
        delete i->second;
    }
}

CLightContainer* CLightContainer::getInstance() 
{
    /**
     * Obtains the single static instance of the container. This attempts to
     * create an instance of this object if it doesn't exist. If it already
     * exists, then return the address of this instance. This uses the
     * singleton methodology.
     * 
     * @static
     * @return CLightContainer* A pointer to the static singleton of the 
     *                          container
     */
    static CLightContainer instance;
    return &instance;
}

CLight *CLightContainer::addLight(string key) 
{
    /**
     * Adds a light into the container. This dynamically creates memory on the
     * heap and saves it for reference.
     *
     * @param string key The reference ID of the light
     * @return CLight* The address of the newely created light.
     */
    CLight* pLight = new CLight;
    m_arrLights.insert(pair<string,CLight*>(key, pLight));
    return pLight ;
}

bool CLightContainer::removeLight(string key) 
{
    /**
     * Removes the light from reference if it exists and clears the memory.
     *
     * @param string key The name of the light to remove.
     * @return bool Whether or not it was successfully removed.
     */
    map<string,CLight*>::iterator i(m_arrLights.find(key));
    if (i == m_arrLights.end())
    {
        return false;
    }
    delete i->second;
    m_arrLights.erase(i);
    return true;
}

CLight *CLightContainer::getLight(string key) const
{
    /**
     * Obtain the light object if the key exists, otherwise return a nullptr.
     *
     * @param string key The name of the light to obtain
     * @return CLight* A pointer to the light, nullptr if cannot be found.
     */
    if (m_arrLights.size() <= 0)
    {
        return nullptr;
    }
    map<string,CLight*>::const_iterator i = m_arrLights.find(key);
    if (i == m_arrLights.end()) 
    {
        return nullptr;
    }
    return i->second;
}


void CLightContainer::setLight(string key, int index, 
                               LPDIRECT3DDEVICE9 pDevice) 
{
    /**
     * Gives a light an index (0 - 7) and tell directx to load the light into
     * the buffer.
     *
     * @param string key The name of the light to give an index
     * @param int index The index of the light to assign
     * @param pDevice The device to assign the light to.
     */
    map<string,CLight*>::iterator i = m_arrLights.find(key);
    i->second->setLight(index, pDevice);
}

void CLightContainer::enableLight(int index, LPDIRECT3DDEVICE9 pDevice) 
{
    /**
     * Turns on a light
     *
     * @param int index The light index to turn on
     * @param pDevice The pointer to the DirectX device
     */
    pDevice -> LightEnable(index, TRUE);
}

void CLightContainer::disableLight(int index, LPDIRECT3DDEVICE9 pDevice) 
{
    /**
     * Turns off a light
     *
     * @param int index The light index to turn off
     * @param pDevice THe pointer to the DirectX device.
     */
    pDevice -> LightEnable(index, FALSE);
}